package com.funsport.util;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

import java.util.HashMap;
import java.util.Map;

/**
 * 微信小程序工具类
 * 处理微信登录、支付等功能
 *
 * @author Fun-Sport Team
 */
@Slf4j
@Component
public class WeChatUtil {

    @Value("${wechat.mini-program.app-id:}")
    private String appId;

    @Value("${wechat.mini-program.app-secret:}")
    private String appSecret;

    private final RestTemplate restTemplate = new RestTemplate();
    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 通过code获取微信openid
     *
     * @param code 微信登录凭证code
     * @return 包含openid和session_key的Map，失败返回null
     */
    public Map<String, String> getWeChatOpenId(String code) {
        log.info("开始调用微信API获取openid, code前缀: {}", code != null ? code.substring(0, Math.min(10, code.length())) : "null");
        
        // 参数校验
        if (code == null || code.trim().isEmpty()) {
            log.error("code参数为空");
            return null;
        }
        
        if (appId == null || appId.trim().isEmpty()) {
            log.error("appId配置为空，请检查application.yml中的wechat.mini-program.app-id配置");
            return null;
        }
        
        if (appSecret == null || appSecret.trim().isEmpty()) {
            log.error("appSecret配置为空，请检查application.yml中的wechat.mini-program.app-secret配置");
            return null;
        }

        String url = "https://api.weixin.qq.com/sns/jscode2session" +
                "?appid=" + appId +
                "&secret=" + appSecret +
                "&js_code=" + code +
                "&grant_type=authorization_code";

        try {
            log.debug("调用微信API: appid={}, code前缀={}", appId, code.substring(0, Math.min(10, code.length())));
            
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
            String responseBody = response.getBody();
            log.info("微信API响应: {}", responseBody);
            
            JsonNode jsonNode = objectMapper.readTree(responseBody);

            // 检查错误码
            if (jsonNode.has("errcode")) {
                int errcode = jsonNode.get("errcode").asInt();
                String errmsg = jsonNode.has("errmsg") ? jsonNode.get("errmsg").asText() : "未知错误";
                
                // 记录详细的错误信息
                log.error("微信登录失败 - errcode: {}, errmsg: {}, code前缀: {}", 
                    errcode, errmsg, code.substring(0, Math.min(10, code.length())));
                
                // 针对常见错误提供详细说明
                switch (errcode) {
                    case 40029:
                        log.error("错误原因：code无效或已使用。微信的code只能使用一次，5分钟内有效。");
                        log.error("解决方案：1. 确保前端不重复调用登录接口；2. code获取后立即使用；3. 检查是否有缓存或重试机制导致code重复使用。");
                        break;
                    case 40013:
                        log.error("错误原因：appid无效");
                        break;
                    case 40163:
                        log.error("错误原因：code已被使用过");
                        break;
                    case -1:
                        log.error("错误原因：系统繁忙，微信服务器错误");
                        break;
                }
                
                return null;
            }

            // 检查必需字段
            if (!jsonNode.has("openid")) {
                log.error("微信API响应中缺少openid字段: {}", responseBody);
                return null;
            }

            Map<String, String> result = new HashMap<>();
            result.put("openid", jsonNode.get("openid").asText());
            
            if (jsonNode.has("session_key")) {
                result.put("session_key", jsonNode.get("session_key").asText());
            }
            
            if (jsonNode.has("unionid")) {
                result.put("unionid", jsonNode.get("unionid").asText());
            }

            log.info("微信登录成功，openid: {}", result.get("openid").substring(0, Math.min(10, result.get("openid").length())) + "...");
            return result;
            
        } catch (Exception e) {
            log.error("调用微信API异常，code前缀: {}", code != null ? code.substring(0, Math.min(10, code.length())) : "null", e);
            return null;
        }
    }

    /**
     * 获取微信access_token（用于发送模板消息等）
     *
     * @return access_token字符串，失败返回null
     */
    public String getAccessToken() {
        String url = "https://api.weixin.qq.com/cgi-bin/token" +
                "?grant_type=client_credential" +
                "&appid=" + appId +
                "&secret=" + appSecret;

        try {
            ResponseEntity<String> response = restTemplate.getForEntity(url, String.class);
            JsonNode jsonNode = objectMapper.readTree(response.getBody());

            if (jsonNode.has("errcode")) {
                log.error("获取access_token失败: {}", response.getBody());
                return null;
            }

            return jsonNode.get("access_token").asText();
        } catch (Exception e) {
            log.error("调用微信API异常", e);
            return null;
        }
    }

    /**
     * 发送微信模板消息
     *
     * @param openid 用户openid
     * @param templateId 模板ID
     * @param data 模板数据
     * @param page 跳转页面路径
     * @return 是否发送成功
     */
    public boolean sendTemplateMessage(String openid, String templateId, Map<String, Object> data, String page) {
        String accessToken = getAccessToken();
        if (accessToken == null) {
            return false;
        }

        String url = "https://api.weixin.qq.com/cgi-bin/message/subscribe/send?access_token=" + accessToken;

        Map<String, Object> payload = new HashMap<>();
        payload.put("touser", openid);
        payload.put("template_id", templateId);
        payload.put("data", data);
        if (page != null) {
            payload.put("page", page);
        }

        try {
            ResponseEntity<String> response = restTemplate.postForEntity(url, payload, String.class);
            JsonNode jsonNode = objectMapper.readTree(response.getBody());

            if (jsonNode.get("errcode").asInt() == 0) {
                return true;
            } else {
                log.error("发送模板消息失败: {}", response.getBody());
                return false;
            }
        } catch (Exception e) {
            log.error("发送模板消息异常", e);
            return false;
        }
    }

    /**
     * 生成小程序二维码
     *
     * @param scene 场景值
     * @param page 跳转页面路径
     * @return 二维码图片字节流，失败返回null
     */
    public byte[] createQRCode(String scene, String page) {
        String accessToken = getAccessToken();
        if (accessToken == null) {
            return null;
        }

        String url = "https://api.weixin.qq.com/wxa/getwxacodeunlimit?access_token=" + accessToken;

        Map<String, Object> payload = new HashMap<>();
        payload.put("scene", scene);
        payload.put("page", page != null ? page : "pages/index/index");
        payload.put("check_path", false);
        payload.put("env_version", "release");

        try {
            ResponseEntity<byte[]> response = restTemplate.postForEntity(url, payload, byte[].class);
            
            // 检查是否是图片
            String contentType = response.getHeaders().getContentType().toString();
            if (contentType.contains("image")) {
                return response.getBody();
            } else {
                log.error("生成二维码失败: 返回非图片内容");
                return null;
            }
        } catch (Exception e) {
            log.error("生成二维码异常", e);
            return null;
        }
    }
}

